# -*- coding: cp1252 -*-
from Tkinter import *
import tkFileDialog
from datetime import datetime, date
import threading
import serial
import pickle

import presentacion.vistas.gui_principal

from instrumento.instrumento import *
from presentacion.vistas import *
#~ from gui_tkinter.gui_tkinter import GuiTkinter


#-----------------------------------------------------------------------
# variables del puerto

#-----------------------------------------------------------------------

fin_s = False





#-----------------------------------------------------------------------
# clases utilizadas
#-----------------------------------------------------------------------




class Bloque:
    def __init__(self, gui):
        """ cada bloque es una lista de medidas mas una variable que
        contiene el indice de la lista, fecha y hora de clibracion,
        temperatura maxima y minima durante la calibracion, material
        """
        self.medidas = []
        for i in range(24):
            self.medidas.append('...')
        self.instancia = 0
        self.instancia_validacion = 0
        self.fecha = str()
        self.hora = str()
        self.material = gui.get_material()
        self.t_max = '...'
        self.t_min = '...'
        self.t_dif = float()

    def __str__(self):
        """ util para debuguear, no se utiliza en el programa
        """
        s  = "medidas tomadas: " + str(self.medidas)
        s += "\ninstancia de medicion actual: cilo " + str(self.instancia//8+1) + ", medida " + str(self.instancia%8+1)
        return s

    def set_valor(self, valor):
        """ asignar valor para una medicion determinada
        """
        if self.instancia==0 and isinstance(self.medidas[self.instancia], str):
            fecha = datetime.now()
            self.fecha = datetime.date(fecha)
            self.hora = datetime.time(fecha)
        self.medidas[self.instancia] = valor
    def set_instancia(self, valor):
        """ elegir la instancia de medicion para el bloque actual
        haciendo click sobre el boton que indica la medida
        """
        self.instancia = valor
    def set_material(self, material):
        self.material = material
    def set_t_max(self, t):
        self.t_max = t
    def set_t_min(self, t):
        self.t_min = t
    def set_instancia_validacion(self, instancia_validacion):
        self.instancia_validacion = instancia_validacion

    def get_medidas(self):
        return self.medidas
    def get_instancia(self):
        return self.instancia
    def get_fecha(self):
        return self.fecha
    def get_hora(self):
        return self.hora
    def get_material(self):
        return self.material
    def get_t_max(self):
        return self.t_max
    def get_t_min(self):
        return self.t_min
    def get_instancia_validacion(self):
        return self.instancia_validacion

    def check(self):
        """ determina si a un bloque le faltan datos de medicion
        devuelve verdadero si todas las medidas son tipo float
        """
        var = True
        for i in range(24):
            var = var and isinstance(self.medidas[i], float)
        return var





def temperatura(data):
    """ actualiza t max y min del bloque actual
    """
    t_max = bloques[numero_bloque].get_t_max()
    t_min = bloques[numero_bloque].get_t_min()
    if bloques[numero_bloque].get_instancia() == 1:
        bloques[numero_bloque].set_t_max(data)
        bloques[numero_bloque].set_t_min(data)
    else:
        bloques[numero_bloque].set_t_max(max(t_max, data))
        bloques[numero_bloque].set_t_min(min(t_min, data))
    t_max = bloques[numero_bloque].get_t_max()
    t_min = bloques[numero_bloque].get_t_min()
    return round(t_max - t_min, 2)


def hex2cen(hexa): # instrumento-.
    """ funion que recibe el dato que devuelve el termometro y devuelve
    la temperatura en grados centigrados
    la curva que devuelve la temperatura en grados se ajusta con ensayos
    y con los datos de calibracion del aparato
    """
    t_ref = 19.95
    value_ref = 4300703     # 'n0'
    data_f = hexa[-6:]      # 'n' desordenado en hexadecimal
    value_absh = data_f[4:6]+data_f[2:4]+data_f[0:2]    # 'n' en hexadecimal
    print value_absh
    value_abs = int('0x'+value_absh,0)  # 'n'
    print value_abs
    t = t_ref + (value_abs - value_ref)*0.00048940814   # t = t_ref + a*(n - n0)
    return t

def medicion_testo(temp):
    temperatura(temp)
    t_max = bloques[numero_bloque].get_t_max()
    t_min = bloques[numero_bloque].get_t_min()
    programa.set_temp(t_max, t_min)


def leer():
    """ lectura de RS-232 (cuando fin=1 se termina el thread)
    luego de la lectura se solicita la temperatura al termometro
    ?como llegue hasta aca?
     1 abrir_puertos(puertos_disponibles, True)

     2 intenta cerrar las conecciones
     3 abre los puertos
     4 inicia "lectura: leer()"
    """

    while not(fin_s):
        lectura_t = 3
        try:
            data = tesa.leer()
            distancia = float(data)
            print distancia
            medicion_tesa(distancia)
        except:
            print "Excepcion: error tesa..."
        while lectura_t != 0:
            try:
                temp = testo.leer()
                print temp
                medicion_testo(float(temp))
                lectura_t = 0
            except:
                print "Excepcion: error testo..."
                lectura_t -= 1
                print 'intentos restantes: ' + str(lectura_t)

def abrir_puertos(puertos_disponibles, inicial=False):
    """ intenta cerrar las conexiones serie y
    luego los abre (en caso de que los puertos est?n disponibles)
    se llama luego de crear los instrumentos:
    abrir_puertos(puertos_disponibles, True)
    """
    print 'reabre'
    tesa.terminar()
    testo.terminar()
    if len(puertos_disponibles)>1:
        print 'inicia testo'
        puerto_testo = puertos_disponibles[1]
        if inicial:
            testo.set_port(puerto_testo, 1200, 'E', 7, 2)
        testo.iniciar(puerto_testo)
    else:
        pass # informar en la barra de estado

    if len(puertos_disponibles)>0:
        print 'inicia tesa'
        puerto_tesa = puertos_disponibles[0]
        if inicial:
            tesa.set_port(puerto_tesa, 1200, 'E', 7, 2)
        tesa.iniciar(puerto_tesa)
        lectura.start()
    else:
        pass # informar en la barra de estado

#-----------------------------------------------------------------------
# iniciar programa principal
#-----------------------------------------------------------------------

#initialize()

  # puerto serie

tesa = Tesa()
testo = Testo()
lectura = threading.Thread(target=leer)

puertos_disponibles = Instrumento.scan_ports(30)
print puertos_disponibles
abrir_puertos(puertos_disponibles, True)